/*
 * Copyright (c) 2008, Solido Systems
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * Neither the name of Solido Systems nor the names of its contributors may be
 * used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

package com.solidosystems.objectkitchen.index;

import java.io.*;
import java.util.*;

public class GroupPage{
	private String group;
	private List<String> members;
	private long nextPage;
	private long lastPage;
	private int payloadSize;
	private int payloadUsage;
	private boolean newpage;
	private int newmembers;
	
	public GroupPage(String group,int payloadSize){
		this.group=group;
		this.members=new ArrayList<String>();
		this.nextPage=-1;
		this.lastPage=-1;
		this.payloadSize=payloadSize;
		this.payloadUsage=0;
		newpage=true;
		newmembers=0;
	}
	
	private GroupPage(String group,long nextPage,long lastPage, int payloadSize,int payloadUsage,List<String> members){
		this.group=group;
		this.members=members;
		this.nextPage=nextPage;
		this.lastPage=lastPage;
		this.payloadSize=payloadSize;
		this.payloadUsage=payloadUsage;
		newpage=false;
		newmembers=0;
	}
	
	public List<String> getMembers(){
		return members;
	}
	
	public int getPayloadSize(){
		return payloadSize;
	}
	
	public void setNextPage(long offset){
		this.nextPage=offset;
	}
	
	public long getNextPage(){
		return nextPage;
	}
	
	public void setLastPage(long offset){
		this.lastPage=offset;
	}
	
	public long getLastPage(){
		return lastPage;
	}
	
	public boolean hasRoom(String id){
		if(payloadSize-payloadUsage>4+id.length()*2)return true;
		return false;
	}
	
	public void add(String id){
		members.add(id);
		payloadUsage+=4+id.length()*2;
		newmembers++;
	}
	
	public static GroupPage readFromFile(DataInput file) throws IOException{
		String group=file.readUTF();
		long nextPage=file.readLong();
		long lastPage=file.readLong();
		int payloadSize=file.readInt();
		int payloadUsage=file.readInt();
		int membercount=file.readInt();
		List<String> members=new ArrayList<String>();
		for(int i=0;i<membercount;i++){
			StringBuilder buf=new StringBuilder();
			int stringSize=file.readInt();
			for(int n=0;n<stringSize;n++){
				buf.append(file.readChar());
			}
			members.add(buf.toString());
		}
		return new GroupPage(group,nextPage,lastPage,payloadSize,payloadUsage,members);
	}
	
	public void writeMetaToFile(DataOutput file) throws IOException{
		file.writeUTF(group);
		file.writeLong(nextPage);
		file.writeLong(lastPage);
		file.writeInt(payloadSize);
		file.writeInt(payloadUsage);
		file.writeInt(members.size());
	}
	
	public void writeToFile(DataOutput file) throws IOException{
		file.writeUTF(group);
		file.writeLong(nextPage);
		file.writeLong(lastPage);
		file.writeInt(payloadSize);
		file.writeInt(payloadUsage);
		file.writeInt(members.size());
		for(String str:members){
			file.writeInt(str.length());
			file.writeChars(str);
		}
		if(newpage)file.write(new byte[payloadSize-payloadUsage]);
	}
	
	public void writeUpdateToFile(RandomAccessFile file) throws IOException{
		file.writeUTF(group);
		file.writeLong(nextPage);
		file.writeLong(lastPage);
		file.writeInt(payloadSize);
		file.writeInt(payloadUsage);
		file.writeInt(members.size());
		int skip=0;
		int skipped=0;
		for(int i=0;i<members.size()-newmembers;i++){
			skip+=4;
			skip+=members.get(i).length()*2;
		}
		while(skipped<skip)skipped+=file.skipBytes(skip-skipped);
		for(int i=members.size()-newmembers;i<members.size();i++){
			String str=members.get(i);
			file.writeInt(str.length());
			file.writeChars(str);
		}
		if(newpage)file.write(new byte[payloadSize-payloadUsage]);
	}
}